package com.ld.shieldsb.common.core.util.notice.wechat.application.taskcard;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableList;
import com.ld.shieldsb.common.composition.util.ConvertUtil;
import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.collections.MapUtils;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.util.JsoupUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.core.util.notice.wechat.EweChatTool;
import com.ld.shieldsb.common.core.util.notice.wechat.Type;
import com.ld.shieldsb.common.core.util.notice.wechat.application.EweChatApplicationParams;
import com.ld.shieldsb.common.core.util.notice.wechat.application.EwechatBasicMsgSender;
import com.ld.shieldsb.common.core.util.notice.wechat.application.EwechatResponse;
import com.ld.shieldsb.common.core.util.notice.wechat.log.EweChatLogFactory;
import com.ld.shieldsb.common.core.util.notice.wechat.log.EweChatLogModel;

/**
 * 任务卡片
 * 
 * @ClassName TaskCardMsgSender
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2021年9月14日 上午9:55:53
 *
 */
public class TaskCardMsgSender extends EwechatBasicMsgSender {

    // ============================================= 任务卡片消息 ==============================================

    /**
     * 
     * 转换任务卡片格式dataMap，仅企业微信3.1.6及以上版本支持,<br>
     * 特殊说明：<br>
     * <br>
     * 任务卡片消息的展现支持简单的markdown语法，详情请见附录支持的markdown语法 。<br>
     * 要发送该类型的消息，应用必须配置好回调URL，详见配置应用回调，用户点击任务卡片的按钮后，企业微信会回调任务卡片事件到该URL，配置的URL按任务卡片更新消息协议返回数据即可。<br>
     * 开发者可以通过更新任务卡片消息状态接口更新卡片状态。
     * 
     * @Title parse2TaskCardDataMap
     * @author 吕凯
     * @date 2021年4月20日 上午9:14:45
     * @param agentid
     * @param sendTo
     * @param taskId
     * @param title
     * @param description
     * @param url
     * @param btns
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Map<String,Object>
     */

    public static Map<String, Object> parse2TaskCardDataMap(String agentid, String sendTo, String taskId, String title, String description,
            String url, List<EweChatTaskCardBtn> btns, Integer duplicateCheckInterval) {
        /*{
        "touser" : "UserID1|UserID2|UserID3",
        "toparty" : "PartyID1 | PartyID2",
        "totag" : "TagID1 | TagID2",
        "msgtype" : "interactive_taskcard",
        "agentid" : 1,
        "interactive_taskcard" : {
            "title" : "赵明登的礼物申请",
            "description" : "礼品：A31茶具套装\n用途：赠与小黑科技张总经理",
            "url" : "URL",
            "task_id" : "taskid123",
            "btn":[
                {
                    "key": "key111",
                    "name": "批准",
                    "color":"red",
                    "is_bold": true
                },
                {
                    "key": "key222",
                    "name": "驳回"
                }
            ]
        },
        "enable_id_trans": 0,
        "enable_duplicate_check": 0,
        "duplicate_check_interval": 1800
        }*/

        Map<String, Object> dataMap = defaultDataMap(agentid, sendTo, duplicateCheckInterval);

        dataMap.put(EweChatTool.MSG_TYPE, Type.INTERACTIVE_TASKCARD.value);

        Map<String, Object> dataTextMap = new HashMap<>();
        dataTextMap.put(TITLE, title); // 必须有，标题，不超过128个字节，超过会自动截断（支持id转译）
        if (StringUtils.isNotEmpty(description)) {
            dataTextMap.put("description", description); // 可无，描述，不超过512个字节，超过会自动截断（支持id转译）
        }
        if (StringUtils.isNotEmpty(url)) {
            dataTextMap.put("url", url); // 可无，点击后跳转的链接。最长2048字节，请确保包含了协议头(http/https)
        }
        dataTextMap.put("task_id", taskId); // 必须有，任务id，同一个应用发送的任务卡片消息的任务id不能重复，只能由数字、字母和“_-@”组成，最长支持128字节
        List<Map<String, Object>> btnDataList = new ArrayList<>();
        dataTextMap.put("btn", btnDataList);
        if (ListUtils.isNotEmpty(btns)) {
            for (EweChatTaskCardBtn btnObj : btns) {
                Map<String, Object> map;
                try {
                    map = ConvertUtil.obj2OrigMap(btnObj);
                    map.remove("class");
                    map = MapUtils.toUnderlineStringMap(map);
                    btnDataList.add(map);
                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    log.error("", e);
                }
            }
        }
        /*btn     是   按钮列表，按钮个数为1~2个。
        btn:key     是   按钮key值，用户点击后，会产生任务卡片回调事件，回调事件会带上该key值，只能由数字、字母和“_-@”组成，最长支持128字节
        btn:name    是   按钮名称
        btn:color   否   按钮字体颜色，可选“red”或者“blue”,默认为“blue”
        btn:is_bold     否   按钮字体是否加粗，默认false
        enable_id_trans     否   表示是否开启id转译，0表示否，1表示是，默认0
        enable_duplicate_check  否   表示是否开启重复消息检查，0表示否，1表示是，默认0
        duplicate_check_interval    否   表示是否重复消息检查的时间间隔，默认1800s，最大不超过4小时*/

        dataMap.put(Type.INTERACTIVE_TASKCARD.value, dataTextMap);
//        System.out.println(JSONObject.toJSONString(dataMap));
        return dataMap;
    }

    public static Map<String, Object> parse2TaskCardDataMap(String agentid, String sendTo, String taskId, String title, String description,
            String url, List<EweChatTaskCardBtn> btns) {
        return parse2TaskCardDataMap(agentid, sendTo, taskId, title, description, url, btns, null);
    }

    public static Result sendTaskCardMsg(String corpid, String corpsecret, String agentid, String sendTo, String taskId, String title,
            String description, String url, List<EweChatTaskCardBtn> btns, Integer duplicateCheckInterval) {
        return sendMsg(corpid, corpsecret, agentid,
                parse2TaskCardDataMap(agentid, sendTo, taskId, title, description, url, btns, duplicateCheckInterval));

    }

    public static Result sendTaskCardMsg(String corpid, String corpsecret, String agentid, String sendTo, String taskId, String title,
            String description, String url, List<EweChatTaskCardBtn> btns) {
        return sendTaskCardMsg(corpid, corpsecret, agentid, sendTo, taskId, title, description, url, btns, null);

    }

    /**
     * 
     * 发送任务卡片消息
     * 
     * @Title sendTaskCardMsg
     * @author 吕凯
     * @date 2021年4月20日 下午6:04:09
     * @param sendTo
     * @param taskId
     * @param title
     * @param description
     * @param url
     * @param btns
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Result
     */
    public static Result sendTaskCardMsg(String sendTo, String taskId, String title, String description, String url,
            List<EweChatTaskCardBtn> btns, Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTaskCardMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, taskId, title, description, url,
                btns, duplicateCheckInterval);
    }

    public static Result sendTaskCardMsg(String sendTo, String taskId, String title, String description, String url,
            List<EweChatTaskCardBtn> btns) {
        return sendTaskCardMsg(sendTo, taskId, title, description, url, btns, null);
    }

    public static Result sendTaskCardMsgAudit(String sendTo, String taskId, String title, String description, String url,
            Integer duplicateCheckInterval) {
        return sendTaskCardMsgAudit(sendTo, taskId, title, description, url, ImmutableList.of("通过", "退回"), duplicateCheckInterval);
    }

    public static Result sendTaskCardMsgAudit(String sendTo, String taskId, String title, String description, String url) {
        return sendTaskCardMsgAudit(sendTo, taskId, title, description, url, ImmutableList.of("通过", "退回"), null);
    }

    public static Result sendTaskCardMsgAudit(String sendTo, String taskId, String title, String description, String url,
            List<String> btnNames, Integer duplicateCheckInterval) {
        List<EweChatTaskCardBtn> btns = new ArrayList<>();
        EweChatTaskCardBtn btnOk = new EweChatTaskCardBtn();
        btnOk.setKey("keyok");
        btnOk.setName(btnNames.get(0));
        btnOk.setIsBold(true);
        EweChatTaskCardBtn btnCancel = new EweChatTaskCardBtn();
        btnCancel.setKey("keyCancel");
        btnCancel.setName(btnNames.get(1));
        btnCancel.setColor("red");
        btns.add(btnOk);
        btns.add(btnCancel);
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTaskCardMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, taskId, title, description, url,
                btns, duplicateCheckInterval);
    }

    public static Result sendTaskCardMsgAudit(String sendTo, String taskId, String title, String description, String url,
            List<String> btnNames) {
        return sendTaskCardMsgAudit(sendTo, taskId, title, description, url, btnNames, null);
    }

    public static Result sendTaskCardMsgConfirm(String sendTo, String taskId, String title, String description, String url,
            Integer duplicateCheckInterval) {
        return sendTaskCardMsgConfirm(sendTo, taskId, title, description, url, "确认", duplicateCheckInterval);
    }

    public static Result sendTaskCardMsgConfirm(String sendTo, String taskId, String title, String description, String url) {
        return sendTaskCardMsgConfirm(sendTo, taskId, title, description, url, "确认", null);
    }

    /**
     * 发送确认任务卡片
     * 
     * @Title sendTaskCardMsgConfirm
     * @author 吕凯
     * @date 2021年4月21日 下午4:31:10
     * @param sendTo
     * @param taskId
     *            必须有，任务id，同一个应用发送的任务卡片消息的任务id不能重复，只能由数字、字母和“_-@”组成，最长支持128字节
     * @param title
     *            标题
     * @param description
     *            表述
     * @param url
     * @param btnNames
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Result
     */
    public static Result sendTaskCardMsgConfirm(String sendTo, String taskId, String title, String description, String url, String btnName,
            Integer duplicateCheckInterval) {
        List<EweChatTaskCardBtn> btns = new ArrayList<>();
        EweChatTaskCardBtn btnOk = new EweChatTaskCardBtn();
        btnOk.setKey("keyok");
        btnOk.setName(btnName);
        btnOk.setIsBold(true);
        btns.add(btnOk);
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTaskCardMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, taskId, title, description, url,
                btns, duplicateCheckInterval);
    }

    public static Result sendTaskCardMsgConfirm(String sendTo, String taskId, String title, String description, String url,
            String btnName) {
        return sendTaskCardMsgConfirm(sendTo, taskId, title, description, url, btnName, null);
    }

    /**
     * 更新任务卡片
     * 
     * @Title updateTaskcard
     * @author 吕凯
     * @date 2021年4月21日 上午9:21:19
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     *            发送给，多个用户用|逗号分隔
     * @param taskId
     * @param replaceName
     * @return Result
     */
    @SuppressWarnings("unchecked")
    public static Result updateTaskcard(String corpid, String corpsecret, String agentid, String sendTo, String taskId,
            String replaceName) {
        Result result = getAccessToken(corpid, corpsecret, agentid);
        if (result.getSuccess()) { // 0是成功
            String accessToken = result.getMessage();
            String sendUrl = String.format(URL_UPDATE_TASKCARD, accessToken);
            Map<String, Object> data = new HashMap<>();
            data.put("userids", sendTo.split("\\|")); // 企业的成员ID列表（消息接收者，最多支持1000个）。多个接收者用‘|’分隔
            data.put(AGENTID, agentid); // 应用的agentid
            data.put("replace_name", replaceName); // 设置替换文案
            data.put("task_id", taskId); // 发送任务卡片消息时指定的task_id

            EweChatLogModel.EweChatLogModelBuilder<?, ?> builder = EweChatLogModel.builder();
            builder.type(EweChatTool.APPLICATION).corpid(corpid).corpsecret(corpsecret).agentid(agentid).token(accessToken)
                    .msgType("updateTaskcard").sendTo(sendTo).data(data);

            JSONObject jsonResult = JsoupUtil.sendJson(data, sendUrl, EweChatTool.USER_AGENT, 10000);
            if (jsonResult != null) {

                EwechatResponse response = JSONObject.toJavaObject(jsonResult, EwechatResponse.class);
                result.setData(response);

                Integer errcode = response.getErrcode();
                String errmsg = response.getErrmsg(); // 信息
                String responseCode = response.getResponseCode(); // 响应码
                String msgId = response.getMsgid(); // 响应码
//                Integer errcode = jsonResult.getInteger(EweChatTool.ERRCODE);
//                String errmsg = jsonResult.getString(EweChatTool.ERRMSG); // 信息
//                String responseCode = jsonResult.getString(RESPONSE_CODE); // 响应码
//                String msgId = jsonResult.getString(MSGID); // 响应码

                // 未发送成功的用户，这个与其他消息不同是数组!!!!!!!
                List<String> invaliduser = jsonResult.getObject(INVALID_USER, List.class);
                String invaliduserString = invaliduser != null ? String.join("|", invaliduser) : null;
                response.setInvaliduser(invaliduserString);

                builder.errcode(errcode).errmsg(errmsg).responseCode(responseCode).msgid(msgId).invaliduser(invaliduserString);

                result.setMessage(errmsg);
                if (errcode == 0) { // 0是成功
                    result.setSuccess(true);
                    builder.success(EweChatTool.SUCCESS);
                } else {
                    result.setSuccess(false);
                    builder.success(EweChatTool.ERROR);
                    if (ListUtils.isNotEmpty(invaliduser)) {
                        result.setMessage("发送失败的用户：" + invaliduser);
                    }
                }
                log.debug(jsonResult + "");
            }

            EweChatLogFactory.saveLog(builder.build()); // 调用保存日志的方法，没有实现需要具体项目自己实现
        }
        return result;

    }

    /**
     * 更新任务卡片状态
     * 
     * @Title updateTaskcard
     * @author 吕凯
     * @date 2021年4月21日 上午9:24:52
     * @param sendTo
     * @param taskId
     * @param replaceName
     * @return Result
     */
    public static Result updateTaskcard(String sendTo, String taskId, String replaceName) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return updateTaskcard(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, taskId, replaceName);
    }

}
